/*
 * jquery.Message-1.0.0.js 自定义弹窗插件，可以自定义模块、按钮数量( 最佳3个以内 )、动态改变标题内容[一次定义多次使用]、支持鼠标拖动、事件链式写法
 * https://gitee.com/kinvirgo/Message
 * 使用方式 : var app = Message()、 var app = Message({Object})
 * version : 1.0.0
 * 事件 API :
 * show()/hide() 显示/隐藏
 * setMessageTitle()/setMessageBody() 设置标题/内容( 设置标题：前提是支持header模块 )
 * update() 更新(支持重构当前弹窗结构 [如果重构弹窗:建议重新声明一个新Message()],重构弹窗结构后无法返回到上一次弹框接口)
 * 更新&更改日志:
 *  log : 201709271104 创建
 *  log : 201710081205 fadeIn/fadeOut 替换 show/hide 动画,同时添加了speed动画时间
 *
 *
 * */
;(function($,window,document,undefined){
    var uiMessage = function(option){
        this.p = $.extend({
            width : 400, // message 宽度
            height : 120, //message body的 高度
            title : '弹窗标题', //弹窗标题(需要设置 header模块支持 )
            content : '这里是弹窗显示的内容  支持自定义html格式', // 这里是弹窗显示的内容  支持自定义html格式
            module : ['header','body','footer'], // 弹窗包含模块 header、body、footer 组合不分先后
            buttons : ['确认','取消'], // 按钮列表显示文本， 目前最大支持3个按钮 暂只支持对称排列
            drag : false, //是否支持鼠标拖动 ( 注意 ： 要支 持拖动 必须包含 header 模块)
            close : true, //是否支持（右上角 需要设置 header模块支持 ）关闭功能
            bodyAuto : false, //用于内容提多显示不全 自动滚动
            speed : 200, //动画过渡速度
            buttonClick : undefined, // 按钮事件
            closeClick : undefined, // header关闭按钮事件(需要设置 header模块 和 close 支持)
            mask : true // 是否开启蒙层 ()
        },option);
        this.mark = "m-id"; // 标识符
        this.id = Math.random().toString(36).slice(-6); // 唯一id标识符
        this.messageClassName = "sn-message-html"; // 弹窗容器class名
        this.headerClassName = "sn-message-header"; // 弹窗头部class名
        this.bodyClassName = "sn-message-body"; // 弹窗内容class名
        this.footerClassName = "sn-message-footer"; // 弹窗底部class名
        this.messageTitleClassName = "sn-message-title"; //弹窗title class名
        this.messageCloseClassName = "sn-message-btnClose"; //弹窗关闭按钮 Class名
        this.messageBtnClassName = "sn-message-button"; //按钮class名
        this.maskClassName = "sn-message-mask"; // 弹窗蒙层class名
    };
    uiMessage.prototype.init = function(){
        var _this = this;
        //1.创建message-html容器
        createMessageHtml( _this );

        //2.创建message-header
        createMessageHeader( _this );

        //3.创建message-body
        createMessageBody( _this );

        //4.创建message-footer
        createMessageFooter( _this );

        //5.创建message-mask
        createMessageMask( _this );

        //6.绑定注册事件
        onMessage( _this );

    };
    //显示
    uiMessage.prototype.show = function(opt){
        var _this = this;
        //更新配置 目前支持更新 标题、内容、事件
        if( opt && !$.isEmptyObject( opt ) ){
            _this.p = $.extend( _this.p, opt);
            setMessageTitle( _this );
            setMessageBody( _this );
        }
        this.messageHtml.fadeIn(_this.p.speed);
        ! this.messageMask || this.messageMask.fadeIn(_this.p.speed);
        return this;
    };
    //隐藏
    uiMessage.prototype.hide = function(){
        this.messageHtml.fadeOut(this.p.speed); 
        ! this.messageMask || this.messageMask.fadeOut(this.p.speed);
        return this;
    };
    //设置标题
    uiMessage.prototype.setMessageTitle = function(title){
        var _this = this;
        if( title != undefined ){
            _this.p.title = title;
            setMessageTitle( _this );
        }else{
            !$this.messageTitle || console.warn("setMessageTitle() 参数未定义,无法修改!");
        }
        return this;
    };
    //设置内容
    uiMessage.prototype.setMessageBody = function(content){
        var _this = this;
        if( content != undefined ){
            _this.p.content = content;
            setMessageBody( _this );
        }else{
            console.warn("setMessageBody() 参数未定义,无法修改!");
        }
        return this;
    };
    //设置按钮文本
    uiMessage.prototype.setMessageButton = function(index, text){
        var currButton = this.messageButton[index];
        !currButton || currButton.html( text );
        return this;
    };
    //禁止按钮 不传递arr表示禁用所有按钮
    uiMessage.prototype.setMessageButtonDisabled = function(arr){
        if( !arr ){
            //没有传递参数禁用所有按钮
            !this.messageButton || this.messageButton.forEach(function(item,index){
                item.addClass("sn-message-disabled").attr("disabled",true);
            });
            !this.messageBtnClose || this.messageBtnClose.addClass("sn-message-disabled").attr("disabled",true);
        }else if( $.isArray(arr) ){
            !this.messageButton || this.messageButton.forEach(function(item,index){
               arr.indexOf( index ) == -1 || item.addClass("sn-message-disabled").attr("disabled",true);
            });
            //删除按钮禁用
            if( arr.indexOf( -1 ) > -1 ){
                !this.messageBtnClose || this.messageBtnClose.addClass("sn-message-disabled").attr("disabled",true);
            }
        }else {
            console.warn("setMessageButtonDisabled() 参数错误!" );
        }
        return this;
    };
    //移除禁止按钮 不传递arr表示禁用所有按钮
    uiMessage.prototype.removeMessageButtonDisabled = function(arr){
        if( !arr ){
            //没有传递参数禁用所有按钮
            !this.messageButton || this.messageButton.forEach(function(item,index){
                item.removeClass("sn-message-disabled").attr("disabled",false);
            });
            !this.messageBtnClose || this.messageBtnClose.removeClass("sn-message-disabled").attr("disabled",false);
        }else if( $.isArray(arr) ){
            !this.messageButton || this.messageButton.forEach(function(item,index){
               arr.indexOf( index ) == -1 || item.removeClass("sn-message-disabled").attr("disabled",false);
            });
            //删除按钮禁用
            if( arr.indexOf( -1 ) > -1 ){
                !this.messageBtnClose || this.messageBtnClose.removeClass("sn-message-disabled").attr("disabled",false);
            }
        }else {
            console.warn("setMessageButtonDisabled() 参数错误!" );
        }
        return this;
    };
    //更新配置 可以重构弹框结构
    uiMessage.prototype.update = function( opt ){
        var _this = this;

        if( opt && !$.isEmptyObject( opt ) ){
            _this.p = $.extend( _this.p, opt);
        }

        //2.创建message-header
        !this.messageHeader || this.messageHeader.remove();
        createMessageHeader( _this );

        //3.创建message-body
        this.messageBody.remove();
        createMessageBody( _this );

        //4.创建message-footer
        !this.messageFooter || this.messageFooter.remove();
        createMessageFooter( _this );

        //5.创建message-mask
        !this.messageMask || this.messageMask.remove();
        createMessageMask( _this );

        //6.绑定注册事件
        onMessage( _this );

        return this;
    };

    function createMessageHtml($this){
        var mHtml = $("<div></div>");
        mHtml.addClass( $this.messageClassName ).attr( $this.mark, $this.id ).css({
            "box-sizing" : "border-box",
            width : $this.p.width
        });

        !( !+'\v1' ) || mHtml.addClass("sn-message-ie8");

        //动态计算message-html 高度
        var mHtmlHeight = $this.p.height;
        mHtmlHeight += ($this.p.module.indexOf("header") != -1 ? 40 : 0);
        mHtmlHeight += ($this.p.module.indexOf("footer") != -1 ? 50 : 0);

        if( $this.p.drag && $this.p.module.indexOf("header") != -1 ){
            //开启鼠标拖动 & 有header模块
            mHtml.css({
                top : ( $(document).innerHeight() - mHtmlHeight )/2,
                left : ( $(document).innerWidth() - $this.p.width )/2
            })
        }else{
             mHtml.css({
                top : "50%",
                left : "50%",
                "margin-top" : -mHtmlHeight/2,
                "margin-left" : -$this.p.width/2
            })
        }

        $("body").append(mHtml);
        $this.messageHtml = mHtml;
    }

    function createMessageHeader($this){
        if( $this.p.module.indexOf("header") == -1 ){
            $this.messageHeader = null;
            return ;
        }
        var mHeader = $("<div></div>");
        mHeader.addClass( $this.headerClassName ).attr( $this.mark, $this.id );

        var mHeaderTitle = $("<span></span>");
        mHeaderTitle.addClass( $this.messageTitleClassName ).attr( $this.mark, $this.id );
        mHeaderTitle.html( $this.p.title );
        mHeader.append( mHeaderTitle );
        $this.messageTitle = mHeaderTitle;

        if( $this.p.close ){
            var mHeaderClose = $('<i></i>');
            mHeaderClose.addClass( $this.messageCloseClassName ).attr( $this.mark, $this.id ).attr( "button-number","-1" );
            mHeaderClose.html( "×" );
            mHeader.append( mHeaderClose );
            $this.messageBtnClose = mHeaderClose;
        }

        $this.messageHtml.append( mHeader );
        $this.messageHeader = mHeader;
    }

    function createMessageBody( $this ){
        var mBody = $("<div></div>");
        mBody.addClass( $this.bodyClassName ).attr( $this.mark, $this.id ).css( "height", $this.p.height );
        if( $this.p.bodyAuto ){
            mBody.addClass("sn-message-bodyAuto");
        }
        mBody.html( $this.p.content );
        $this.messageHtml.append( mBody );
        $this.messageBody = mBody;
    }

    function createMessageFooter($this){
        $this.messageButton = [];
        if( $this.p.module.indexOf("footer") == -1 ){
            return null;
        }
        var mFooter = $("<div></div>");
        mFooter.addClass( $this.footerClassName ).attr( $this.mark, $this.id );


        $this.p.buttons.forEach(function(item, index){
            var btnDiv = $("<div></div>");
                btnDiv.attr( $this.mark, $this.id );
                btnDiv.addClass( "sn-message-btnContent" );
                btnDiv.css("width",1/$this.p.buttons.length*100+'%');

            var button = $("<button></button>");
                button.attr( $this.mark, $this.id );
                button.attr('button-number',index);
                button.addClass( $this.messageBtnClassName );
                button.html( item ) ;

            btnDiv.append( button );
            $this.messageButton.push( button );

            mFooter.append( btnDiv );
        });

        $this.messageHtml.append( mFooter );
        $this.messageFooter = mFooter;
    }

    function createMessageMask($this){
        if( !$this.p.mask ){
            $this.messageMask = null;
            return;
        }
        var mask = $("<div></div>");
        mask.attr( $this.mark, $this.id );
        mask.addClass( $this.maskClassName );
        $("body").append(mask);
        $this.messageMask = mask;
    }

    function onMessage($this){
        //绑定底部按钮事件
        $this.messageButton.forEach(function(item,index){
            //先清除已经绑定的事件
            item.unbind();
            item.on("messageClick",function(event,index){
                var data = {};
                data.number = index;
                data.button = $(this);
                !(typeof $this.p.buttonClick === "function" ) || $this.p.buttonClick(data,$this);
                $this.messageHtml.fadeOut($this.p.speed); 
                ! $this.messageMask || $this.messageMask.fadeOut($this.p.speed)
            });
            //通过单击事件绑定中间件( 中间事件 便于以后做更新等操作 )
            item.click(function(event){
                $(this).trigger("messageClick",[index]);
            })
        });

        !$this.messageBtnClose || $this.messageBtnClose.unbind();
        //绑定右上角关闭按钮
        !$this.messageBtnClose || $this.messageBtnClose.click(function(event){
            if( $(this).attr("disabled") === "disabled" ){
                return;
            }
            var data = {};
            data.number = -1;
            data.button = $(this);
            !(typeof $this.p.closeClick === "function" ) || $this.p.closeClick(data,$this);

            $this.messageHtml.fadeOut($this.p.speed); 
            ! $this.messageMask || $this.messageMask.fadeOut($this.p.speed);
        });
        //注册鼠标拖动事件
        if( $this.messageHeader && $this.p.drag ){
            drag( $this.messageHeader, $this.messageHtml);
        }
    }

    function setMessageTitle($this){
        !$this.messageTitle || $this.messageTitle.html( $this.p.title );
    }

    function setMessageBody($this){
        $this.messageBody.html( $this.p.content );
    }

    /* 注册拖动事件
     * @param $m [jquery obj]
     * @param $w [jquery obj]
     * */
    function drag($m,$w){
        var d=document,
        x,
        y,
        p='onmousemove';
        $m.mousedown(function(e){
            $(".sn-message-zIndex").removeClass("sn-message-zIndex");
            $w.addClass("sn-message-zIndex");
            $m.addClass("sn-message-cursorMove");
            e=e||event;
            x=e.clientX-$m.offset().left;
            y=e.clientY-$m.offset().top;
            d[p]=function(e){
                e=e||event;
                $w.css({
                    left : e.clientX-x+'px',
                    top : e.clientY-y+'px'
                })
            };
            d.onmouseup=function(){
                d[p]=null;
                $m.removeClass("sn-message-cursorMove");
            }
        })
    }

    if ( !Array.prototype.indexOf ) {
        Array.prototype.indexOf = function ( ele ) {
            // 获取数组长度
            var len = this.length;
            // 检查值为数字的第二个参数是否存在，默认值为0
            var fromIndex = Number( arguments[ 1 ] ) || 0;
            // 当第二个参数小于0时，为倒序查找，相当于查找索引值为该索引加上数组长度后的值
            if ( fromIndex < 0 ) {
                fromIndex += len;
            }
            // 从fromIndex起循环数组
            while ( fromIndex < len ) {
                // 检查fromIndex是否存在且对应的数组元素是否等于ele
                if ( fromIndex in this && this[ fromIndex ] === ele ) {
                    return fromIndex;
                }
                fromIndex++;
            }
            // 当数组长度为0时返回不存在的信号：-1
            return -1;
        }
    }

    if ( !Array.prototype.forEach ) {
        Array.prototype.forEach = function forEach( callback ) {
            // 获取数组长度
            var len = this.length;
            if ( typeof callback != "function" ) {
                throw new TypeError();
            }
            // thisArg为callback 函数的执行上下文环境
            var thisArg = arguments[ 1 ];
            for ( var i = 0; i < len; i++ ) {
                if ( i in this ) {
                    // callback函数接收三个参数：当前项的值、当前项的索引和数组本身
                    callback.call( thisArg, this[ i ], i, this );
                }
            }
        }
    }

    window.Message = function(option){
        var app = new uiMessage(option);
        app.init();
        return app;
    }
})(jQuery,window,document);
